--[[
	MadDogs Damage System coded by MadDog
	Version: 	1.01
	Author:	Drew Gauderman (aka MadDog)
	Email:	drew(at)aspinvison(dot)com
	Created: 	June 04 2008
	Updated: 	Sep 6 2009
]]

local meta = FindMetaTable( "Entity" )

function meta:Health()
	if (self:GetNWInt("Health") == 0) then
		self:SetNWInt("Health", self:GetMaxHealth() )
	end

	return self:GetNWInt("Health")
end

function meta:SetHealth( health )
	self:SetNWInt("Health", health)
end

function meta:GetMaxHealth()
	if (self:GetNWInt("MaxHealth") > 0) then return self:GetNWInt("MaxHealth") end

	local phys = self:GetPhysicsObject()
	local weight = 100

	if phys:IsValid() then weight = phys:GetMass() end

	if (weight < 0) then weight = 100 end

	local health = math.Clamp(math.ceil(weight * 5), 0, 4000)

	self:SetMaxHealth(health)

	return health
end

function meta:SetMaxHealth( health )
	self:SetNWInt("MaxHealth", health)
end

function meta:GiveHealth( amount )
	self:SetNWInt("Health", math.Clamp((self:Health() + amount), 0, self:GetMaxHealth()))
end

function meta:TakeHealth( amount )
	self:SetNWInt("Health", math.Clamp((self:Health() - amount), -1, self:GetMaxHealth()))
end













function MDDS.Setup( ent )
	--if turned off, exit
	if (!IsValid(ent)) or (ent:IsWorld()) or (ent:IsWeapon()) or (ent:IsPlayer()) or (ent:IsNPC()) or (ent.MDDSRegenerateThink) then return end

	--add think function
	function ent:MDDSRegenerateThink()
		--if not valid, exit
		if (!self:IsValid()) then return end

		--randomly give health back
		self:GiveHealth(math.random(4, 15))

		--max health color (no damage color that is)
		local healthColor = 255

		--the less damage we get, the lighter the color gets
		if (ent:Health() != ent:GetMaxHealth()) then healthColor = ((ent:Health()/ent:GetMaxHealth()) * 100) * 255 / 100 end

		--set color
		ent:SetColor(healthColor, healthColor, healthColor, 255)

		--remove timer if back to normal health
		if (self:Health() == self:GetMaxHealth()) then timer.Destroy( "MDDS" .. ent:EntIndex() ) end
	end
end

function MDDS.TakeDamage( ent, inflictor, attacker, amount, dmg )
	if (!MDDS.IsEnabled()) or (!IsValid(ent)) or (ent:IsWorld()) or (ent:IsWeapon()) or (ent:IsPlayer()) or (ent:IsNPC()) then return end

	--if explode damage is caused by the same prop, exit (to prevent stack overflow errors)
	if (dmg:IsExplosionDamage()) and (!dmg:GetAttacker():IsPlayer()) then return end

	local owner = ent:GetOwner()

	if (!attacker:IsPlayer()) then attacker:GetOwner() end --get owner for checks
	if (!attacker:IsPlayer()) then return false end --no player then no damage
	if (!MDDS.IsFriend( owner, friend )) then return false end --not a friend so no damage


	MsgN("BOOM! ", amount)

	--setup entity with the damage system
	MDDS.Setup( ent )

	--take out the damage
	ent:TakeHealth(amount)

	--the more damage we get, the darker the color gets
	local healthColor = ((ent:Health()/ent:GetMaxHealth()) * 100) * 255 / 100
	ent:SetColor(healthColor, healthColor, healthColor, 255)

	--if damage is below zero, remove it
	if (ent:Health() <= 0) then
		return MDDS.Destory(ent)
	--create regenerate timer
	elseif !timer.IsTimer( "MDDS" .. ent:EntIndex() ) then
		timer.Create("MDDS" .. ent:EntIndex(), 1, 0, function()
			if IsValid(ent) then ent:MDDSRegenerateThink() end
		end)
	end
end

--this hook will hook anything created, except vehicles :(
hook.Add( "EntityTakeDamage", "MDDS.TakeDamage", MDDS.TakeDamage )		--entity created, add damage hook

function MDDS.Destory( ent )
	--remove any timers
	timer.Destroy( "MDDS" .. ent:EntIndex() )

	--local vars
	local size, pos = (ent:BoundingRadius() / 2), ent:GetPos()

	--do some blast damage, hehe
	util.BlastDamage(ent, ent, pos, size * 2, size * 4)

	--remove it!
	ent:Remove()

	--set explode effect
	local Effect = EffectData()
	Effect:SetOrigin(pos)
	Effect:SetScale(size)
	Effect:SetRadius(size)
	Effect:SetMagnitude(size)
	util.Effect("HelicopterMegaBomb", Effect)

	--2nd effect
	util.Effect("Explosion", Effect)
end

function MDDS.IsFriend( ply, friend )
	if (ply == friend) then return true end

	--other pp
	if (CPPI and ply.CPPIGetFriends) then
		local friends = ply:CPPIGetFriends()

		for _,friend in pairs(friends) do
			if ply == friend then return true end
		end
	--simple prop protection check
	elseif (!SPropProtectionEnabled) then
		return true
	end

	--buddy check
	return SPropProtection.PlayerCanTouch(ply, ent)
end